<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2019/2/16 0016
 * Time: 13:42
 */
namespace app\wx_api\ext\auth;

use app\wx_api\ext\auth\SignAbstract;
use app\common\app2\AppConfig;

/**
 * 平台的签名与验证
 * 对参数进行加密的签名验证
 * Class Sign
 * @package app\common\lib\auth
 */
class Sign extends SignAbstract{

    const EXPIRED_TIME = 60; // 签名过期时间
    public $error_msg = null;

    /**
     * 验证签名
     * @param $data
     * @return bool
     */
    public function check($data) {
        // 检验签名必要的参数
        if (!isset($data['time']) || empty($data['time']) || !isset($data['client_sign']) || !isset($data['app_id'])) {
            $this->error_msg = '必要参数缺失';
            return false;
        }
        // 验证签名是否过期
        if (time() > $data['time'] + self::EXPIRED_TIME) { // 过期
            $this->error_msg = '无效的签名，签名已过期';
            return false;
        }

        // 校验签名
        if (!$server_sign = $this->generateSign($data)) { // 生成签名失败
            return false;
        }
        // 校验
        if ($data['client_sign'] !== $server_sign) {
            $this->error_msg = '签名验证失败';
            return false;
        }
        return true;
    }

    // 生成服务端的签名
    protected function generateSign($data) {
        unset($data['client_sign']);
        // 将参与签名的参数转成字符串
        $params_str = $this->signArrayToStr($data);
        // 获取对应的app_secret
        if (!$app_secret = AppConfig::getAppSecret($data['app_id'])) {
            $this->error_msg = '平台未获得授权，或授权数据已经失效';
            return false;
        }
        // 生成签名
        return $server_sign = strtoupper(sha1($params_str . $app_secret));
    }


    /**
     * 将参与签名的参数重组成字符串（不包括app_secret）
     * @param $array
     * @return string
     */
    private function signArrayToStr($array) {
        ksort($array);
        $str = '';
        foreach ($array as $k => $v) {
            $str .= ($str)?'&' . $k . '=' . $v : $k . '=' . $v;
        }
        return $str;
    }
}